﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace FCSChart.Graphical
{
    /// <summary>
    /// 四边形
    /// </summary>
    public class RectangleGraphical : PolygonGraphical
    {
        public RectangleGraphical() : base() { }

        public RectangleGraphical(RectangleGraphicalModel model) : base(model) { }

        protected override void InitName()
        {
            this.Name = "Rectangle";
            this.ShortName = "R";
        }

        #region function
        internal override void PanelMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateing && sender is Panel panel && Points.Count <= 0)
            {
                var point = e.GetPosition(panel);
                var x = OwnerChart.XAxis.GetLocationValue(point.X);
                var y = OwnerChart.YAxis.GetLocationValue(point.Y);
                Points.Add(new Point(x, y));
                Points.Add(new Point(x, y));
                Points.Add(new Point(x, y));
                Points.Add(new Point(x, y));
            }
        }
        internal override void PanelMouseMove(object sender, MouseEventArgs e)
        {
            if (IsCreateing && sender is Panel panel && Points.Count == 4)
            {
                var point = e.GetPosition(panel);
                var x = OwnerChart.XAxis.GetLocationValue(point.X);
                var y = OwnerChart.YAxis.GetLocationValue(point.Y);
                Points[2] = new Point(x, y);
                Points[1] = new Point(x, Points[0].Y);
                Points[3] = new Point(Points[0].X, y);
                OnPropertyChanged("Points");
            }
        }
        internal override void PanelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateing)
            {
                if (Points[0] == Points[2]) return;
                OnPropertyChanged("Points");
                IsCreateing = false;
            }
        }

        protected override void Shape_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && sender is Path path && path.Data is EllipseGeometry ellipse)
            {
                var point = e.GetPosition(OwnerChart.ViewPanel);
                var index = ControlShapes.IndexOf(path);
                var value = Converters.AxisValueToViewValueConverter.Converter.ConvertBack(point, null, OwnerChart, null);
                if (value is Point p)
                {
                    Points[index] = p;
                    switch (index)
                    {
                        case 0:
                            Points[1] = new Point(Points[1].X, p.Y);
                            Points[3] = new Point(p.X, Points[3].Y);
                            break;
                        case 1:
                            Points[0] = new Point(Points[0].X, p.Y);
                            Points[2] = new Point(p.X, Points[2].Y);
                            break;
                        case 2:
                            Points[1] = new Point(p.X, Points[1].Y);
                            Points[3] = new Point(Points[3].X, p.Y);
                            break;
                        case 3:
                            Points[0] = new Point(p.X, Points[0].Y);
                            Points[2] = new Point(Points[2].X, p.Y);
                            break;
                        default:
                            break;
                    }
                    OnPropertyChanged("Points");
                    DrawingControl();
                }
                ellipse.Center = point;
                e.Handled = true;
            }
        }
        #endregion
        /// <summary>
        /// 更新门划分的区域内数据
        /// </summary>
        internal override async void RefreshAreaSource(Func<object, double> xValueConverter, Func<object, double> yValueConverter)
        {
            if (Area == null) return;
            if (!isCreateing && Points != null && Points.Count == 4 && OwnerChart != null && OwnerChart.XSource != null && OwnerChart.YSource != null)
            {
                var minX = Points.Min(p => p.X);
                var maxX = Points.Max(p => p.X);
                var minY = Points.Min(p => p.Y);
                var maxY = Points.Max(p => p.Y);
                var xSource = OwnerChart.XSource;
                var ySource = OwnerChart.YSource;
                var count = Math.Min(xSource.Count, ySource.Count);
                var parentIndexs = OwnerChart.Indexs;

                var maxDegreeOfParallelism = OwnerChart.Series == null ? 4 : OwnerChart.Series.MaxDegreeOfParallelism;
                Area.InsideIndexs = await Task.Run(() =>
                {
                    ConcurrentBag<int> indexs = new ConcurrentBag<int>();
                    if (parentIndexs == null)
                    {
                        var result = Parallel.For(0, count, new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism }, (i) =>
                        {
                            var x = xValueConverter == null ? Convert.ToDouble(xSource[i]) : xValueConverter(xSource[i]);
                            var y = yValueConverter == null ? Convert.ToDouble(ySource[i]) : yValueConverter(ySource[i]);
                            if (x >= minX && x <= maxX && y >= minY && y <= maxY) indexs.Add(i);
                        });
                    }
                    else
                    {
                        var result = Parallel.ForEach(parentIndexs, new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism }, (i) =>
                        {
                            var x = xValueConverter == null ? Convert.ToDouble(xSource[i]) : xValueConverter(xSource[i]);
                            var y = yValueConverter == null ? Convert.ToDouble(ySource[i]) : yValueConverter(ySource[i]);
                            if (x >= minX && x <= maxX && y >= minY && y <= maxY) indexs.Add(i);
                        });
                    }
                    return indexs.ToArray();
                });
            }
            else
            {
                Area.InsideIndexs = null;
            }
        }
        /// <summary>
        /// 获取门的数据类型
        /// </summary>
        /// <returns></returns>
        protected override BaseGraphicalModel GetGraphicalMode()
        {
            if (IsCreateing) return null;
            return new RectangleGraphicalModel() { AreaNames = new string[] { Area.Name }, AreaColors = new Color[] { Area.DisplayColor }, Points = this.Points };
        }
    }

    /// <summary>
    /// 四边形数据
    /// </summary>
    public class RectangleGraphicalModel : PolygonGraphicalModel
    {

    }
}
